package com.fwtai.tool;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.fwtai.bean.PageFormData;

import java.io.File;
import java.io.FileWriter;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Stream;

/**
 * 字符串的工具类|含json对象或json数组解析
 * @作者 田应平
 * @版本 v1.0
 * @创建时间 2015年11月27日 18:25:12
 * @QQ号码 444141300
 * @官网 http://www.fwtai.com
 */
public final class ToolString implements Serializable {

  private static final long serialVersionUID = 1L;

  private static final Pattern pattern = Pattern.compile("[\\d]*$");

  /**
   * 转码
   * @param object
   * @return
   * @作者 田应平
   * @返回值类型 String
   * @创建时间 2015-9-6 下午5:23:06
   * @QQ号码 444141300
   * @官网 http://www.blidian.com
  */
  public static String transCoding(final Object object){
    if(object != null){
      try {
        return new String(object.toString().getBytes("ISO8859-1"),"UTF-8");
      } catch (Exception e){
        return null;
      }
    }
    return null;
  }

  /**多线程下生成32位唯一的字符串*/
  public static String getIdsChar32(){
    final ThreadLocalRandom random = ThreadLocalRandom.current();
    return String.valueOf(new UUID(random.nextInt(),random.nextInt())).replaceAll("-","");
  }

  /**判断字符串是否全是数字*/
  public static boolean isNumeric(final String value){
    return value != null && pattern.matcher(value).matches();
  }

  /**生成10个盐*/
  public static String getSalt(){
    final ThreadLocalRandom random = ThreadLocalRandom.current();
    return String.valueOf(new UUID(random.nextInt(),random.nextInt())).replaceAll("-","").substring(22);
  }

  /**
   * 验证是否为空,为空时返回true,否则返回false,含obj是否为 _单独的下划线特殊字符,是则返回true,否则返回false
   * @作者: 田应平
   * @主页 www.fwtai.com
   * @创建日期 2016年8月18日 17:34:24
  */
  public static boolean isBlank(final Object obj){
    if(obj == null)return true;
    if(obj instanceof String){
      final String temp = String.valueOf(obj);
      if(temp.equalsIgnoreCase("null"))return true;
      final String key = obj.toString().replaceAll("\\s*","");
      if(key.equals("") || key.length() <= 0 )return true;
      if(key.length() == 1 && key.equals("_"))return true;
    }
    if(obj instanceof List<?>){
      final List<?> list = (List<?>) obj;
      return list == null || list.size() <= 0;
    }
    if(obj instanceof Map<?,?>){
      final Map<?,?> map = (Map<?,?>) obj;
      return map == null || map.size() <= 0;
    }
    if(obj instanceof String[]){
      boolean flag = false;
      final String[] require = (String[])obj;
      for(int i = 0; i < require.length; i++){
        if(require[i] == null || require[i].length() == 0 || require[i].replaceAll("\\s*", "").length() == 0){
          flag = true;
          break;
        }
      }
      return flag;
    }
    if(obj instanceof HashMap<?,?>){
      final HashMap<?, ?> hashMap = (HashMap<?,?>) obj;
      return hashMap == null || hashMap.size() <= 0;
    }
    if(obj instanceof PageFormData){
      final PageFormData hashMap = (PageFormData)obj;
      return hashMap == null || hashMap.size() <= 0;
    }
    if(obj instanceof JSONObject){
      final JSONObject json = (JSONObject)obj;
      return json.isEmpty();
    }
    return false;
  }

  /**如果为空则赋值为""*/
  public static String setBlank(final Object obj){
    if (isBlank(obj))return "";
    return String.valueOf(obj);
  }

  /**如果为空则赋值为defaultValue*/
  public static String setBlank(final Object obj,final String defaultValue){
    if (isBlank(obj))return defaultValue;
    return String.valueOf(obj);
  }

  /**
   * 去除空格,如果为空则返回null,若有且只有_也只返回null否则去除前后空格后返回
   * @param obj
   * @作者 田应平
   * @返回值类型 String
   * @创建时间 2015-8-18 下午2:03:25
   * @QQ号码 444141300
   * @注释 \s 匹配任何空白字符，包括空格、制表符、换页符,* 匹配前面的子表达式零次或多次。
   * @官网 http://www.fwtai.com
  */
  public static String wipeObject(final Object obj){
    if(isBlank(obj))return null;
    final String key = obj.toString().replaceAll("\\s*", "");
    if(key.length() == 1 && key.equals("_"))return null;
    return key;
  }

  /**
   * 去除空格,如果为空则返回null,若有且只有_也只返回null否则去除前后空格后返回
   * @param value
   * @作者 田应平
   * @返回值类型 String
   * @创建时间 2015-8-18 下午2:03:25
   * @QQ号码 444141300
   * @注释 \s 匹配任何空白字符，包括空格、制表符、换页符,* 匹配前面的子表达式零次或多次。
   * @官网 http://www.fwtai.com
  */
  public static String wipeString(final String value){
    if(value == null || value.length() <= 0)return null;
    final String key = value.replaceAll("\\s*", "");
    if(key.equals("_"))return null;
    return key;
  }

  public static String wipeStrBlank(final String value){
    if(value == null || value.length() <= 0)return null;
    return Pattern.compile("\\s*|\t|\r|\n").matcher(value).replaceAll("");
  }

  /**
   * 是否大于指定长度,若大于返回true否则返回false
   * @param value
   * @param length
   * @作者 田应平
   * @返回值类型 boolean
   * @创建时间 2015-12-22 上午3:25:17
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static boolean isTooLong(final String value,final int length){
    return value.length() > length;
  }

  /**
   * 验证输入值是否是正整数,是正整数返回true,否则返回false
   * @param value
   * @作者 田应平
   * @返回值类型 boolean
   * @创建时间 2015-12-9 下午6:11:36
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static boolean checkNumber(final String value){
    String reg = "^\\d*[1-9]\\d*$";
    Pattern p = Pattern.compile(reg);
    Matcher m = p.matcher(value);
    return m.matches();
  }

  /**
   * 生成时间格式:yyyy-MM-dd HH:mm:ss,不能用static关键字!!
   * @作者 田应平
   * @返回值类型 String
   * @创建时间 2017年1月10日 09:35:02
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public String getTime(){
    return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(ZonedDateTime.now());//设置日期格式
  }

  /**时间戳转为日期（yyyy-MM-dd）*/
  public static String timestampToDate(final String value){
    return timestampToDate(Long.parseLong(value));
  }

  /**时间戳转为日期（yyyy-MM-dd）*/
  public static String timestampToDate(final long value){
    return format(value * 1000,"yyyy-MM-dd");
  }

  /**时间戳转为日期时分秒（yyyy-MM-dd HH:mm:ss）*/
  public static String timestampToDateTime(final String value){
    return timestampToDateTime(Long.parseLong(value));
  }

  /**时间戳转为日期时分秒（yyyy-MM-dd HH:mm:ss）*/
  public static String timestampToDateTime(final long value){
    return format(value * 1000,"yyyy-MM-dd HH:mm:ss");
  }

  private static String format(final long value,final String pattern){
    return new SimpleDateFormat(pattern).format(new java.util.Date(value));
  }

  /**日期转时间戳（yyyy-MM-dd）*/
  public static Long dateToTimestamp(final String value){
    try {
      return parseFormat(value,"yyyy-MM-dd");
    } catch (final ParseException ignored) {
      return null;
    }
  }

  /**日期时分秒（yyyy-MM-dd HH:mm:ss）转时间戳*/
  public static Long dateTimeToTimestamp(final String value){
    try {
      return parseFormat(value,"yyyy-MM-dd HH:mm:ss");
    } catch (final ParseException ignored) {
      return null;
    }
  }

  private static Long parseFormat(final String value,final String pattern) throws ParseException{
    return new SimpleDateFormat(pattern).parse(value).getTime() / 1000;
  }

  /**
   * 生成时间格式:yyyyMMdd,不能用static关键字!!!
   * @return
  */
  public final String getDate(){
    return DateTimeFormatter.ofPattern("yyyyMMdd").format(ZonedDateTime.now());
  }

  /**
   * 生成时间格式:yyyyMMddHHmmss,不能用static关键字!!!
  */
  public final String getDateTime(){
    return DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(ZonedDateTime.now());
  }

  /**
   * ids字符串数组转换为ArrayList<String>,默认是以逗号,隔开
   * @param ids 格式如:12958292,12951500,12977780,12997129
   * @作者 田应平
   * @返回值类型 ArrayList<String>
   * @创建时间 2020年4月10日 01:39:15
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static ArrayList<String> keysToList(final String ids){
    return keysToList(ids,",");
  }

  /**
   * ids字符串数组转换为ArrayList<Long>,默认是以逗号,隔开
   * @param ids 格式如:12958292,12951500,12977780,12997129
   * @作者 田应平
   * @返回值类型 ArrayList<String>
   * @创建时间 2022-05-14 13:21:16
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static ArrayList<Long> keysToListLong(final String ids){
    return keysToListLong(ids,",");
  }

  /**
   * ids字符串数组转换为ArrayList<String>
   * @param ids 格式如:12958292,12951500,12977780,12997129
   * @param splitFlag 以 splitFlag 为拆分标识
   * @作者 田应平
   * @返回值类型 ArrayList<String>
   * @创建时间 2016年1月21日 12:20:36
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static ArrayList<String> keysToList(final String ids,String splitFlag){
    if(ids == null || ids.isEmpty())return null;
    final ArrayList<String> list = new ArrayList<String>();
    if(splitFlag == null){
      splitFlag = ",";
    }
    final String[] arr = ids.split(splitFlag);
    if(arr.length == 0)return null;
    for(int i = 0; i < arr.length; i++){
      list.add(arr[i]);
    }
    return list;
  }

  /**
   * ids字符串数组转换为ArrayList<Long>
   * @param ids 格式如:12958292,12951500,12977780,12997129
   * @param splitFlag 以 splitFlag 为拆分标识
   * @作者 田应平
   * @返回值类型 ArrayList<String>
   * @创建时间 2022-05-14 13:21:39
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static ArrayList<Long> keysToListLong(final String ids,String splitFlag){
    if(ids == null || ids.isEmpty()) return null;
    if(splitFlag == null){
      splitFlag = ",";
    }
    final String[] arrs = ids.split(splitFlag);
    final int length = arrs.length;
    if(length == 0) return null;
    final ArrayList<Long> list = new ArrayList<Long>(length);
    for(int i = length - 1; i >= 0; i--){
      try{
        list.add(Long.parseLong(arrs[i]));
      }catch(final Exception ignored){
        return null;
      }
    }
    return list;
  }

  public static long[] keysToArarry(final String ids){
    return keysToArarry(ids,",");
  }

  /**
   * ids字符串数组转换为String
   * @param ids 格式如:12958292,12951500,12977780,12997129
   * @param splitFlag 以 splitFlag 为拆分标识
   * @作者 田应平
   * @返回值类型 long[]
   * @创建时间 2022-05-28 11:33:24
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static long[] keysToArarry(final String ids,String splitFlag){
    if(ids == null || ids.isEmpty()) return null;
    if(splitFlag == null){
      splitFlag = ",";
    }
    final String[] arrs = ids.split(splitFlag);
    final int length = arrs.length;
    if(length == 0) return null;
    try {
      return Stream.of(arrs).mapToLong(Long::parseLong).toArray();
    } catch (final Exception ignored) {
      return null;
    }
  }

  /**
   * 根据完整文件路径删除文件
   * @作者 田应平
   * @返回值类型 boolean
   * @创建时间 2017年1月10日 09:34:49
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static boolean deleFileByRealPath(final String filePath){
    if(filePath != null && filePath.length() > 0){
      try {
        File f = new File(filePath);
        if(f.exists()){
          f.delete();
        }
        return true ;
      } catch (Exception e){}
    }
    return false ;
  }

  /**
   * html网页的img替换规则
   * @param html
   * @作者 田应平
   * @返回值类型 String
   * @创建时间 2016年1月23日 17:33:21
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
   * @示例 html = html.replaceAll("src=\"/upimg","src=\""+url+"/upimg");
  */
  public static String htmlReplace(final String html,final String flagOld,final String flagNew){
    return html.replaceAll(flagOld,flagNew);
  }

  /**
   * 判断一个字符串是否是纯数字字符串
   * @作者 田应平
   * @返回值类型 boolean
   * @创建时间 2017年3月8日 上午8:23:11
   * @QQ号码 444141300
   * @主页 http://www.fwtai.com
  */
  public static boolean isNumberStr(final String str){
    try {
      Integer.parseInt(str);
      return true;
    } catch (NumberFormatException e){
      return false;
    }
  }

  /**获取文件的后缀名|扩展名*/
  public static String getFileExt(final String str){
    return str.substring(str.lastIndexOf('.')+1,str.length());
  }

  /**验证指定的key字符串是否在以逗号,隔开的字符串里,存在返回true,为false时说明不存在,用法:if(!ToolString.existKey("xls,xlsx",key)){}*/
  public static boolean existKey(final String keys,final String key){
    final String[] array = keys.split(",");
    boolean b = false;
    for(int i = 0; i < array.length; i++){
      if(array[i].equalsIgnoreCase(key)){
        b = true;
        break;
      }
    }
    return b;
  }

  /**获取文件的文件名,不含扩展名后缀名*/
  public static String getFileName(final String str){
    return str.substring(str.lastIndexOf('/')+1,str.lastIndexOf('.'));
  }

  /**获取文件的文件名,含扩展名后缀名*/
  public static String getFileNameExt(final String str){
    return str.substring(str.lastIndexOf('/')+1);
  }

  /**
   * <strong style='color:#f69;'>判断json类型;返回1是json对象;返回2json数组;返回0不是有效的json数据,如要判断是否是json对象判断是否等1或json数组等于2即可</strong>
   * @param json 字符串
   * @作者 田应平
   * @返回值类型 int <strong style='color:#f69;'>返回1是json对象;返回2json数组;返回0不是有效的json数据</strong>
   * @创建时间 2017年3月7日 下午8:46:18
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static int jsonType(final String json){
    if(json == null || json.length() <= 0){
      return 3;
    }
    try {
      if(Pattern.matches("^\\{\".*\\}$",json)){
        JSON.parseObject(json);
        return 1;
      }else if(Pattern.matches("^\\[\\{\".*\\]$",json)){
        JSON.parseArray(json);
        return 2;
      }else {
        return 0;
      }
    } catch (Exception e){
      return 4;
    }
  }

  /**
   * <strong style='color:#f69;'>解析json对象字符串,HashMap里的key未做处理</strong>
   * @提示 <strong style='color:#369;'>json对象就是以{"开头,即HashMap<String,String>;json数组就是以[{"开头,即ArrayList<HashMap<String,String>>;json全都是String</strong>
   * @作者 田应平
   * @创建时间 2017年3月7日 20:42:05
   * @QQ号码 444141300
   * @主页 http://www.fwtai.com
  */
  public static HashMap<String,String> parseJsonObject(final Object json){
    final HashMap<String,String> jsonMap = new HashMap<String,String>();
    if(json == null || json.toString().length() == 0) return jsonMap;
    try {
      final HashMap<String,String> map = JSON.parseObject(json.toString(),new TypeReference<HashMap<String,String>>(){});
      return map == null ? jsonMap : map;
    } catch (Exception e){
      return jsonMap;
    }
  }

  /**
   * 解析json对象字符串,HashMap里的key未做处理
   * @param json
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2020年5月15日 18:26:29
  */
  public static JSONObject parseJsonObj(final String json){
    final JSONObject jsonObject = new JSONObject();
    if(json == null || json.length() == 0) return jsonObject;
    try {
      return JSON.parseObject(json);
    } catch (Exception e){
      return jsonObject;
    }
  }

  /**
   * <strong style='color:#f69;'>解析json数组字符串,ArrayList里的HashMap的key未做处理</strong>
   * @提示 <strong style='color:#369;'>json对象就是以{"开头,即HashMap<String,String>;json数组就是以[{"开头,即ArrayList<HashMap<String,String>>;json全都是String</strong>
   * @作者 田应平
   * @创建时间 2018年6月14日 23:14:02
   * @QQ号码 444141300
   * @主页 http://www.fwtai.com
  */
  public static ArrayList<HashMap<String,String>> parseJsonArray(final Object jsonArray){
    final ArrayList<HashMap<String,String>> listResult = new ArrayList<HashMap<String,String>>();//初始化,以免出现空指针异常
    if(jsonArray == null || jsonArray.toString().length() <= 0) return listResult;
    try {
      final ArrayList<HashMap<String,String>> result = JSON.parseObject(jsonArray.toString(),new TypeReference<ArrayList<HashMap<String,String>>>(){});
      return result == null ? listResult : result;
    } catch (Exception e){
      return listResult;
    }
  }

  /**
   * 解析json数组字符串,List里的PageFormData的key未做处理
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2018年9月29日 13:52:54
  */
  public static List<PageFormData> parseArrayPageFormData(final Object array){
    final List<PageFormData> list = new ArrayList<PageFormData>();
    if(isBlank(array)){return list;}
    final JSONArray jsonArray = JSON.parseArray(array.toString());
    for(int i = 0; i < jsonArray.size(); i++){
      final JSONObject json = jsonArray.getJSONObject(i);
      final PageFormData pageData = new PageFormData();
      for(final String key : json.keySet()){
        pageData.put(key,json.get(key));
      }
      list.add(pageData);
    }
    return list;
  }

  /**
   * 解析json数组字符串,List里的Map<String,Object>的key未做处理
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2018年9月29日 13:52:54
  */
  public static List<Map<String,Object>> parseArrayMap(final Object array){
    final List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
    if(isBlank(array)){return list;}
    final JSONArray jsonArray = JSON.parseArray(array.toString());
    for(int i = 0; i < jsonArray.size(); i++){
      final JSONObject json = jsonArray.getJSONObject(i);
      final Map<String,Object> map = new HashMap<String,Object>();
      for(final String key : json.keySet()){
        map.put(key,json.get(key));
      }
      list.add(map);
    }
    return list;
  }

  /**
   * 解析json数组字符串,List里的HashMap<String,Object>的key未做处理
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2018年12月3日 09:19:26
  */
  public static List<HashMap<String,Object>> parseListHashMap(final Object array){
    final List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();
    if(isBlank(array)){return list;}
    final JSONArray jsonArray = JSON.parseArray(array.toString());
    for(int i = 0; i < jsonArray.size(); i++){
      final JSONObject json = jsonArray.getJSONObject(i);
      final HashMap<String,Object> map = new HashMap<String,Object>();
      for(final String key : json.keySet()){
        map.put(key,json.get(key));
      }
      list.add(map);
    }
    return list;
  }

  /**
   * 解析json数组字符串,ArrayList里的HashMap<String,Object>的key未做处理
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2018年12月3日 09:21:02
  */
  public static ArrayList<HashMap<String,Object>> parseArrayListHashMap(final Object array){
    final ArrayList<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();
    if(isBlank(array)){return list;}
    final JSONArray jsonArray = JSON.parseArray(array.toString());
    for(int i = 0; i < jsonArray.size(); i++){
      final JSONObject json = jsonArray.getJSONObject(i);
      final HashMap<String,Object> map = new HashMap<String,Object>();
      for(final String key : json.keySet()){
        map.put(key,json.get(key));
      }
      list.add(map);
    }
    return list;
  }

  /**
   * <strong style='color:#f69;'>将json字符串解析为一个 JavaBean 对象</strong>
   * @param cls 转换的目标对象
   * @用法 调用时写 StringTools.jsonToObject(json, javaBean.class);
   * @作者 田应平
   * @返回值类型 T
   * @创建时间 2017年3月7日 下午9:12:19
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static <T> T parseJsonToBean(final String json,final Class<T> cls){
    T t = null;
    try {
      t = JSON.parseObject(json,cls);
    } catch (Exception e){
      e.printStackTrace();
    }
    return t;
  }

  /**
   * <strong style='color:#f69;'>将json数组字符串 解析成为一个 List< JavaBean ></strong>
   * @param cls 转换的目标对象
   * @用法 如果是实体类则在调用时写 jsonToListObject(json, javaBean.class);或 jsonToListObject(json,String.class);
   * @作者 田应平
   * @返回值类型 List< T >
   * @创建时间 2017年3月7日 21:15:00
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static <T> List<T> parseJsonToListBean(final String jsonArray,final Class<T> cls){
    List<T> list = new ArrayList<T>();//初始化,以免出现空指针异常
    try {
      list = JSON.parseArray(jsonArray,cls);
    } catch (Exception e){
    }
    return list;
  }

  /**
   * 验证中文
   * @param chinese 中文字符
   * @return 验证成功返回true，验证失败返回false
  */
  public static boolean checkChinese(String chinese) {
    String regex = "^[\u4E00-\u9FA5]+$";
    return Pattern.matches(regex,chinese);
  }

  /**判断是否还有中文或英文字符串*/
  public static int checkString(final String str){
    int res = -1;
    if(str != null){
      for (int i = 0; i < str.length(); i++){
        // 只要字符串中有中文则为中文
        if(!checkChar(str.charAt(i))){
          res = 0;// "中文";
          break;
        } else {
          res = 1;// "英文";
        }
      }
    }
    return res;
  }

  /**判断是否还有中文或英文字符串*/
  public static boolean checkChar(final char ch){
    // 英文
    // 中文
    return (ch + "").getBytes().length == 1;
  }

  /**编辑时判断数据库是否已经存在,queryResultKey是根据要编辑的数据去查询数据库查询出来的主键数值,一般指的是主键;keyEdit是要做对比的对象,一般的是主键,即是根据该keyEdit主键去编辑的数据行*/
  public static boolean editExistKey(final String queryResultKey,final String keyEdit){
    return (queryResultKey != null && queryResultKey.length() > 0) && queryResultKey.equals(keyEdit);
  }

  /**判断是否是格式的yyyy-MM-dd、yyyy.MM.dd的日期格式*/
  public static boolean checkDate(final String date){
    if(date == null || date.length() <=0)return false;
    final String pattern = "\\d{4}(\\-|\\/|.)\\d{1,2}\\1\\d{1,2}";
    return Pattern.matches(pattern,date);
  }

  /**判断是否是格式的yyyy-MM-dd HH:mm:ss、yyyy.MM.dd HH:mm:ss的日期时间格式*/
  public static boolean verifyDateTimeSecond(final String date){
    if(date == null || date.length() <=0)return false;
    final String pattern = "\\d{4}(\\-|\\/|.)\\d{1,2}\\1\\d{1,2}\\s\\d{1,2}:\\d{1,2}:\\d{1,2}";
    return Pattern.matches(pattern,date);
  }

  /**验证金额,0、0.25、25、56.78*/
  public static boolean verifyDecimal(final String value){
    final String pattern = "[0-9]\\d*\\.?\\d*";
    return Pattern.matches(pattern,value);
  }

  /**判断是否是合格的yyyy-MM-dd HH:mm:ss时间格式*/
  public static boolean checkDateTimes(final String dateTime){
    return checkDate(dateTime,"yyyy-MM-dd HH:mm:ss",19);
  }

  /**
   * 判断是否是合格的指定时间格式
   * @param date
   * @param expression  指定日期格式:yyyy-MM-dd HH:mm:ss
   * @作者 田应平
   * @返回值类型 boolean
   * @创建时间 2017年9月14日 上午11:39:46
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static boolean checkDate(final String date,final String expression,final int length){
    if (date == null || date.length() <= 0 || date.length() != length) return false;
    try {
      new SimpleDateFormat(expression).parse(date);
      return true;
    } catch (Exception e){
      return false;
    }
  }

  /**
   * 把字符串写入到指定物理路径文件
   * @作者 田应平
   * @创建时间 2017年10月29日 上午11:04:43
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static boolean writeFile(final String content,final String filePath){
    final File file = new File(filePath);
    try {
      final FileWriter fw = new FileWriter(file);
      fw.write(content);
      fw.close();
      return true;
    } catch (Exception e){
      return false;
    }
  }

  /**
   * 获取window 用户桌面路径
   * @作者 田应平
   * @创建时间 2017年11月2日 上午8:29:20
   * @QQ号码 444141300
   * @官网 http://www.fwtai.com
  */
  public static String getOperationSystemByUserDirectory() {
    final javax.swing.filechooser.FileSystemView fsv = javax.swing.filechooser.FileSystemView.getFileSystemView();
    return fsv.getHomeDirectory().getPath();
  }

  /**验证排序关键字*/
  public static boolean checkOrderKey(final String key){
    final String[] keys = {"ASC","DESC"};
    for(final String value : keys){
      if(key.equalsIgnoreCase(value)){
        return true;
      }
    }
    return false;
  }

  /**
   * 替换关键字,防止SQL注入过滤
   * @param sqlKey
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2018年1月1日 14:24:50
  */
  public static String sqlInject(String sqlKey){
    if(sqlKey == null || sqlKey.length() <= 0)return null;
    //去掉'|"|;|\字符
    sqlKey = sqlKey.replaceAll("'","").replaceAll("\"","").replaceAll(";", "").replaceAll("--", "").replace( "\\", "");
    //转换成小写
    final String key = sqlKey.toLowerCase();
    //非法字符
    final String[] keywords = {"master","truncate","insert","select","delete","update","declare","alert","drop"};
    //判断是否包含非法字符
    for(final String keyword : keywords){
      if(key.contains(keyword)){
        return null;
      }
    }
    return sqlKey;
  }

  /**
   * 判断运行系统是linux还是windows,是linux返回true,否则返回false
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2018年1月23日 15:50:19
  */
  public static boolean isLinuxOS(){
    return System.getProperty("os.name").startsWith("Linux");
  }

  /**
   * json 字符转换为 HashMap 对象
   * @param json 字符串
   * @return
  */
  public static HashMap<String,String> jsonConvertHashMap(final String json){
    return JSON.parseObject(json,HashMap.class);
  }

  /**
   * 判断某个字符串中出现了几次
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2019/8/14 20:57
  */
  public static int count(final String text,final String sub){
    int count = 0, start = 0;
    while((start=text.indexOf(sub,start))>=0){
      start += sub.length();
      count ++;
    }
    return count;
  }

  /**
   * 将请求参数转换为xml格式的string
   * @param parameters 请求参数
   * @return
  */
  public static String getRequestXml(SortedMap<Object, Object> parameters) {
    final StringBuilder sb = new StringBuilder();
    sb.append("<xml>");
    final Set es = parameters.entrySet();
    final Iterator it = es.iterator();
    while (it.hasNext()) {
      final Map.Entry entry = (Map.Entry) it.next();
      final String k = (String) entry.getKey();
      final String v = (String) entry.getValue();
      if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)) {
        sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
      } else {
        sb.append("<" + k + ">" + v + "</" + k + ">");
      }
    }
    sb.append("</xml>");
    return sb.toString();
  }

  /**检测传入的参数是否排序关键字,true说明是排序关键字*/
  public static boolean checkInjectKey(final String key){
    final String[] arr = {"ASC","DESC"};
    for(int i = 0; i < arr.length; i++){
      if(key.equalsIgnoreCase(arr[i])){
        return true;
      }
    }
    return false;
  }

  /**检测传入的参数是否带sql的注释符号*/
  public static boolean checkInject(final String key){
    return key.contains("--");
  }

  /**
   * (高级筛选)检测传入指定字段[示例]
   * @param column 需要检测的列
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2019/11/30 12:41
  */
  public static boolean checkAdvancedFiltrate(final String column){
    if(column != null && column.length() > 0){
      return checkExistColumn(column,new String[]{"eval_level","money"});
    }
    return false;
  }

  /**
   * 检测传入指定字段
   * @param column 需要检测的列
   * @param columns 需要检测的列的集合
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2019/11/30 12:40
  */
  public static boolean checkExistColumn(final String column,final String... columns){
    if(column == null )return false;
    for(int x = 0; x < columns.length; x++){
      if(column.equals(columns[x])){
        return true;
      }
    }
    return false;
  }

  /**处理手机号中间4位替换成**/
  public static String replacePhone(final String phone){
    if(phone == null)
      return null;
    return phone.length() >6 ? phone.substring(0,3)+"****"+phone.substring(7) : phone.substring(0,2)+"****"+phone.substring(5);
  }

  private static final Pattern HK_PATTERN = Pattern.compile("^(5|6|8|9)\\d{7}$");
  private static final Pattern CHINA_PATTERN = Pattern.compile("^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$");

  /**
   * 大陆号码或香港号码均可
  */
  public static boolean verifyPhone(final String phone){
    try {
      return isChinaPhoneLegal(phone) || isHKPhoneLegal(phone);
    } catch (final Exception e) {
      return false;
    }
  }

  /**
   * 大陆手机号码11位数，匹配格式：前三位固定格式+后8位任意数
   * 此方法中前三位格式有：
   * 13+任意数
   * 145,147,149
   * 15+除4的任意数(不要写^4，这样的话字母也会被认为是正确的)
   * 166
   * 17+3,5,6,7,8
   * 18+任意数
   * 198,199
  */
  public static boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
    return CHINA_PATTERN.matcher(str).matches();
  }

  /**
   * 香港手机号码8位数，5|6|8|9开头+7位任意数
  */
  public static boolean isHKPhoneLegal(String str) throws PatternSyntaxException {
    return HK_PATTERN.matcher(str).matches();
  }

  /** Blob转为String类型 */
  public static String blobConvertStr(final byte[] bytes){
    return new String(bytes);
  }

  /** Blob转为String类型 */
  public static String blobConvertStr(final byte[] bytes,final String charset){
    return new String(bytes,Charset.forName(charset));
  }

  /**
   * <strong style='color:#f69;'>解析json对象字符串,HashMap里的key未做处理</strong>,final
   * @提示 <strong style='color:#369;'>json对象就是以{"开头,即HashMap<String,String>;json数组就是以[{"开头,即ArrayList<HashMap<String,String>>;json全都是String</strong>
   * @作者 田应平
   * @创建时间 2017年3月7日 20:42:05
   * @QQ号码 444141300
   * @主页 http://www.fwtai.com
  */
  public static HashMap<String,String> parseJsonObjectOriginal(final Object json){
    final HashMap<String, String> jsonMap = new HashMap<String, String>();
    if(isBlank(json)) return jsonMap;
    try {
      final JSONObject jsonObject = JSON.parseObject(json.toString());
      for (final String key : jsonObject.keySet()){
        final Object obj = jsonObject.get(key);
        if(obj != null){
          final String value = obj.toString().trim();
          if(value.length() <= 0)
            continue;
          if(value.length() == 1 && value.equals("_"))
            continue;
          jsonMap.put(key,value);
        }
      }
      return jsonMap;
    } catch (Exception e){
      return jsonMap;
    }
  }

  /**
   * <strong style='color:#f69;'>解析json数组字符串,ArrayList里的HashMap的key未做处理</strong>,final
   * @提示 <strong style='color:#369;'>json对象就是以{"开头,即HashMap<String,String>;json数组就是以[{"开头,即ArrayList<HashMap<String,String>>;json全都是String</strong>
   * @作者 田应平
   * @创建时间 2018年6月14日 23:14:02
   * @QQ号码 444141300
   * @主页 http://www.fwtai.com
  */
  public static ArrayList<HashMap<String,String>> parseJsonArrayOriginal(final Object jsonArray){
    final ArrayList<HashMap<String, String>> listResult = new ArrayList<HashMap<String, String>>();
    if(isBlank(jsonArray)) return listResult;
    try {
      ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();//初始化,以免出现空指针异常
      list = JSON.parseObject(jsonArray.toString(), new TypeReference<ArrayList<HashMap<String, String>>>(){});
      if(list != null && list.size() > 0){
        for (int i = 0; i < list.size(); i++){
          final HashMap<String, String> hashMap = new HashMap<String, String>();
          final HashMap<String,String> map = list.get(i);
          for(final String key : map.keySet()){
            final Object obj = map.get(key);
            if(obj != null){
              final String value = obj.toString().trim();
              if(value.length() <= 0)
                continue;
              if(value.length() == 1 && value.equals("_"))
                continue;
              hashMap.put(key,value);
            }
          }
          listResult.add(hashMap);
        }
        return listResult;
      } else {
        return listResult;
      }
    } catch (Exception e){
      return listResult;
    }
  }

  /**Unicode转中文汉字*/
  public static String unicodeDecode(String string) {
    Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
    Matcher matcher = pattern.matcher(string);
    char ch;
    while (matcher.find()) {
      ch = (char) Integer.parseInt(matcher.group(2), 16);
      string = string.replace(matcher.group(1), ch + "");
    }
    return string;
  }

  /**
   * 适用于element-ui的批量删除操作,返回值可能是list<String>也可能是list<Bean>
   * @param jsonArray
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2020年5月28日 21:04:08
  */
  public static ArrayList<Object> jsonArrayToList(final Object jsonArray){
    final JSONArray arrays = parseJSONArray(String.valueOf(jsonArray));
    return new ArrayList<>(arrays);
  }

  /**
   * 解析json对象字符串
  */
  public static JSONArray parseJSONArray(final String json){
    final JSONArray array = new JSONArray();
    if(json == null || json.length() <= 0) return array;
    try {
      return JSON.parseArray(json.trim());
    } catch (Exception e){
      return array;
    }
  }

  /**随机生成验证码*/
  public static String getRandomCode(){
    final StringBuilder sb = new StringBuilder();
    final Random random = new Random();
    final String str = "0123456789";
    for (int i = 0; i < 6; i++) {
      final char word = str.charAt(random.nextInt(str.length()));
      sb.append(word);
    }
    return sb.toString();
  }

  /**判断list是否有重复值*/
  public static boolean checkDuplication(final ArrayList<String> list){
    final HashSet<String> set = new HashSet<>(list);
    return list.size() == set.size();
  }

  /**处理前端行政区域的单选树形列表的区域*/
  public static void handlerAreaData(final PageFormData formData,final String key){
    final String areaData = formData.getStringRemove("areaData");
    if(areaData !=  null){
      final HashMap<String,String> map = ToolString.parseJsonObject(areaData);
      final String grade = map.get("grade");
      if(grade != null){
        final Integer type = Integer.valueOf(grade);
        if(key != null){
          formData.put(key,type);//代理等级的key及value,1`省|市`;2`地州市`;3`区|县`;4`乡|镇|社区`
        }
        switch (type){
          case 1://仅选`省|市`1级别,1个
            formData.put("province_id",Long.parseLong(map.get("1")));
            break;
          case 2://选`地州市`级别,2个
            formData.put("province_id",Long.parseLong(map.get("1")));
            formData.put("city_id",Long.parseLong(map.get("2")));
            break;
          case 3://选`区|县`级别,3个
            formData.put("province_id",Long.parseLong(map.get("1")));
            formData.put("city_id",Long.parseLong(map.get("2")));
            formData.put("county_id",Long.parseLong(map.get("3")));
            break;
          case 4://选`乡|镇|社区`级别,4个;代理商的特殊区域id
            formData.put("province_id",Long.parseLong(map.get("1")));//省|市
            formData.put("city_id",Long.parseLong(map.get("2")));//地州市
            formData.put("county_id",Long.parseLong(map.get("3")));//区|县
            formData.put("towns_id",Long.parseLong(map.get("4")));//乡|镇|社区
            formData.put("area_id",map.get(grade));//特殊区域,如有需求先在xml里判断是否存在该key
            break;
          default:
            break;
        }
      }
    }
  }
}